

USE64

TTY.ROWS	EQU	25
TTY.COLUMNS	EQU	80
TTY.TAB_LENGTH	EQU	8
TTY.SCREEN_BUFFER	EQU	0B8000h

TTY.currentRow		db	0
TTY.currentColumn	db	0

; bool TTY.printString(char* str, // rcx
;			UINT8 row, // dl
;			UINT8 column, // dh
;			char endChar, // edx(23:16)
;			UINT8 color);	// edx(31:24)
TTY.printString:
LABEL	.row	AT	rsp+8
LABEL	.col	AT	rsp+8+1
LABEL	.endC	AT	rsp+8+2
LABEL	.color	AT	rsp+8+3
	mov	[rsp+8],	rdx
	test	rcx,	rcx
	jz	.false
	cmp	dl,	TTY.ROWS
	jae	.false
	movzx	rax,	BYTE [.col]
	cmp	al,	TTY.COLUMNS
	jae	.false
	
	mov	[TTY.currentRow],	dl
	mov	[TTY.currentColumn],	al
	movzx	rdx,	dl
	lea	rdx,	[4*rdx+rdx]	; rdx *= 5
	shl	rdx,	5		; rdx *= 16 * 2
	lea	r9,	[rdx+2*rax+TTY.SCREEN_BUFFER]
	
	mov	ax,	[.color]
.loop0:
	mov	al,	[rcx]
	inc	rcx
	cmp	al,	[.endC]
	je	.true
	
.checkBackspace:
	cmp	al,	8
	jne	.checkTab
	cmp	BYTE [TTY.currentColumn],	0
	jne	.else0
	cmp	BYTE [TTY.currentRow],	0
	je	.false
	dec	BYTE [TTY.currentRow]
	mov	BYTE [TTY.currentColumn],	TTY.COLUMNS - 1
	jmp	.endif0
.else0:
	dec	BYTE [TTY.currentColumn]
.endif0:
	sub	r9,	2
	jmp	.loop0
	
.checkTab:
	cmp	al,	9
	jne	.checkCarriage
	mov	dl,	[TTY.currentColumn]
	and	dl,	TTY.TAB_LENGTH - 1
	mov	r8b,	TTY.TAB_LENGTH
	sub	r8b,	dl
	mov	dl,	[TTY.currentColumn]
	add	dl,	r8b
	
	cmp	dl,	TTY.COLUMNS
	jb	.else1
	mov	dl,	[TTY.currentRow]
	inc	dl
	cmp	dl,	TTY.ROWS
	jae	.false
	mov	BYTE [TTY.currentColumn],	0
	inc	BYTE [TTY.currentRow]
	jmp	.endif1
.else1:
	mov	[TTY.currentColumn],	dl
.endif1:
	mov	al,	' '
.loop1:
	mov	[r9],	ax
	add	r9,	2
	dec	r8b
	jnz	.loop1
	jmp	.loop0
	
.checkCarriage:
	cmp	al,	10
	jne	.checkLineFeed
	movzx	rdx,	BYTE [TTY.currentColumn]
	shl	rdx,	1
	sub	r9,	rdx
	mov	BYTE [TTY.currentColumn],	0
	jmp	.loop0
	
.checkLineFeed:
	cmp	al,	13
	jne	.otherChar
	mov	dl,	[TTY.currentRow]
	inc	dl
	cmp	dl,	TTY.ROWS
	jae	.false
	inc	BYTE [TTY.currentRow]
	add	r9,	TTY.COLUMNS * 2
	jmp	.loop0
	
.otherChar:
	mov	dl,	[TTY.currentColumn]
	inc	dl
	cmp	dl,	TTY.COLUMNS
	jb	.else2
	mov	dl,	[TTY.currentRow]
	inc	dl
	cmp	dl,	TTY.ROWS
	jae	.false
	inc	BYTE [TTY.currentRow]
	mov	BYTE [TTY.currentColumn],	0
	jmp	.endif2
.else2:
	inc	BYTE [TTY.currentColumn]
.endif2:
	mov	[r9],	ax
	add	r9,	2
	jmp	.loop0
	
.true:
	mov	rax,	1
	ret
.false:
	xor	rax,	rax
	ret
	